package com.vivek.guess.what.calculation;

import static com.vivz.guess.what.util.GuessWhatUtil.getDifferenceAgainstGuess;

import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import com.vivz.guess.what.type.Position;
import com.vivz.guess.what.vo.Clue;
import com.vivz.guess.what.vo.Guess;

/**
 * <pre>
 * 3. Check for the definite insiders with their probable positions
 * 
 * Check all the guessed words' weights that match the regex : [.]+ against the zero weights.
 * 
 * Use case #1: you have .'s = valid diff betn 0-weight word and guess-word
 * KING ----
 * GRIT ..
 * .R.T valid diff (Here you know for sure that the position of R and T is definitely NOT 2 and 4 respectively)
 * 
 * Use case #2: you have .'s > diff betn 0-weight word and guess-word
 * KING ----
 * WILD ..
 * W.LD valid diff (Here you know for sure that the position of W, L and T is definitely NOT 1, 3 and 4 respectively)
 * 
 * Use case #3: you have .'s < diff betn 0-weight word and guess-word [NOT POSSIBLE]
 * (Possible when the opponent is a human and has probably given a wrong weighted clue)
 * KING ----
 * RING ..
 * R... valid diff
 * 
 * </pre>
 */
public class ZeroPlus0Calculation extends AbstractCalculation {

	@Override
	public void calculate(final List<Guess> guesses, final Map<Character, Set<Position>> probabilityMap) {

		if (isInputValid(guesses, probabilityMap)) {

			for (final Guess zeroWtGuess : guesses) {
				final Clue zero = zeroWtGuess.getClue();

				if (zero.hasDash()) {

					for (final Guess g : guesses) {
						final Clue clue = g.getClue();

						if (!clue.hasCrosses() && clue.hasDots()) {
							final Map<Character, Position> difference = getDifferenceAgainstGuess(g, zeroWtGuess);

							if (difference.isEmpty()) {
								/* This is one of the possibilities in the Use case #3 - boo hoo */

							} else {
								final int diff = difference.size();
								final int count0 = clue.getCount0();

								final Set<Entry<Character, Position>> differenceEntries = difference.entrySet();
								final Iterator<Entry<Character, Position>> differenceEntryIterator = differenceEntries
										.iterator();

								if (diff == count0) {

									// This is the Use case #1
									while (differenceEntryIterator.hasNext()) {
										final Entry<Character, Position> differenceEntry = differenceEntryIterator
												.next();
										final Character differenceCharacter = differenceEntry.getKey();
										final Position differenceCharacterPosition = differenceEntry.getValue();
										final Set<Position> set = probabilityMap.get(differenceCharacter);
										set.remove(differenceCharacterPosition);

										// -- This should be taken care in removeEmptyPositionSets() --
										// // If the set is empty after removing the value remove the key from the map
										// if (set.isEmpty()) {
										// // This should not happen as we have a . for each key in the clue - boo hoo
										// probabilityMap.remove(differenceCharacter);
										// } else {
										// // DEFINITE_INSIDERS.add(key);
										// }
									}

								} else if (diff > count0) {
									// This is the Use case #2
									while (differenceEntryIterator.hasNext()) {
										final Entry<Character, Position> entry = differenceEntryIterator.next();
										final Character key = entry.getKey();
										final Position value = entry.getValue();
										final Set<Position> set = probabilityMap.get(key);
										set.remove(value);

										// -- This should be taken care in removeEmptyPositionSets() --
										// // If the set is empty after removing the value remove the key from the map
										// if (set.isEmpty()) {
										// probabilityMap.remove(key);
										// } else {
										// // PROBABLE_INSIDERS.add(key);
										// }
									}
								} else {
									// This is one of the possibilities in the Use case #3 - boo hoo
								}
							}
						}
					}
				}
			} // end for

			removeEmptyPositionSets(probabilityMap);
		}
	}

}
